package com.sl.core.engine.transfer;

import com.sl.core.domain.dto.JsonMappingFieldDefine;
import com.sl.core.utils.JsonUtil;

import java.util.*;

public class JoltSpecGenerator {

    public static String transfer(List<JsonMappingFieldDefine> fieldDefineList) {
        JoltSpecGenerator joltSpecGenerator = new JoltSpecGenerator();
        List<Map<String, Object>> specList = joltSpecGenerator.generateJoltSpec(fieldDefineList);
        return JsonUtil.toStr(specList);
    }

    public List<Map<String, Object>> generateJoltSpec(List<JsonMappingFieldDefine> rootFields) {
        List<Map<String, Object>> operations = new ArrayList<>();

        Map<String, Object> shiftOperation = new LinkedHashMap<>();
        shiftOperation.put("operation", "shift");
        Map<String, Object> shiftSpec = new LinkedHashMap<>();

        for (JsonMappingFieldDefine rootField : rootFields) {
            processField(rootField, shiftSpec, new Stack<>(), 0);
        }

        shiftOperation.put("spec", shiftSpec);
        operations.add(shiftOperation);
        return operations;
    }

    private void processField(JsonMappingFieldDefine field,
                              Map<String, Object> parentSpec,
                              Stack<String> pathStack,
                              int level) {

        String sourceKey = field.getMappingJsonPath();
        if (sourceKey == null || sourceKey.isEmpty()) {
            sourceKey = field.getFieldCode();
        } else {
            sourceKey = extractLastFieldNameFromJsonPath(sourceKey);
        }

        // 如果是数组
        if (field.isArray() && field.getChildren() != null && !field.getChildren().isEmpty()) {
            Map<String, Object> arraySpec = new LinkedHashMap<>();
            parentSpec.put(sourceKey, arraySpec);

            Map<String, Object> elementSpec = new LinkedHashMap<>();
            arraySpec.put("*", elementSpec);

            pathStack.push(sourceKey);

            for (JsonMappingFieldDefine child : field.getChildren()) {
                processArrayElement(child, elementSpec, pathStack, level + 1);
            }

            pathStack.pop();
        }
        // 如果是对象嵌套结构
        else if (field.getChildren() != null && !field.getChildren().isEmpty()
                && !"String".equalsIgnoreCase(field.getFieldType())
                && !"Integer".equalsIgnoreCase(field.getFieldType())
                && !"Double".equalsIgnoreCase(field.getFieldType())
                && !"Boolean".equalsIgnoreCase(field.getFieldType())) {

            Map<String, Object> childSpec = new LinkedHashMap<>();
            parentSpec.put(sourceKey, childSpec);

            pathStack.push(sourceKey);

            for (JsonMappingFieldDefine child : field.getChildren()) {
                processField(child, childSpec, pathStack, level + 1);
            }

            pathStack.pop();
        }
        // 叶子节点
        else {
            String targetPath = buildTargetPath(pathStack, field);
            parentSpec.put(sourceKey, targetPath);
        }
    }

    private void processArrayElement(JsonMappingFieldDefine field,
                                     Map<String, Object> elementSpec,
                                     Stack<String> pathStack,
                                     int level) {

        String sourceKey = field.getMappingJsonPath();
        if (sourceKey == null || sourceKey.isEmpty()) {
            sourceKey = field.getFieldCode();
        } else {
            sourceKey = extractLastFieldNameFromJsonPath(sourceKey);
        }

        if (field.isArray() && field.getChildren() != null && !field.getChildren().isEmpty()) {
            Map<String, Object> arraySpec = new LinkedHashMap<>();
            elementSpec.put(sourceKey, arraySpec);

            Map<String, Object> subElementSpec = new LinkedHashMap<>();
            arraySpec.put("*", subElementSpec);

            pathStack.push(sourceKey);

            for (JsonMappingFieldDefine child : field.getChildren()) {
                processArrayElement(child, subElementSpec, pathStack, level + 1);
            }

            pathStack.pop();
        }
        else if (field.getChildren() != null && !field.getChildren().isEmpty()
                && !"String".equalsIgnoreCase(field.getFieldType())
                && !"Integer".equalsIgnoreCase(field.getFieldType())
                && !"Double".equalsIgnoreCase(field.getFieldType())
                && !"Boolean".equalsIgnoreCase(field.getFieldType())) {

            Map<String, Object> childSpec = new LinkedHashMap<>();
            elementSpec.put(sourceKey, childSpec);

            pathStack.push(sourceKey);

            for (JsonMappingFieldDefine child : field.getChildren()) {
                processField(child, childSpec, pathStack, level + 1);
            }

            pathStack.pop();
        }
        else {
            String targetPath = buildTargetPath(pathStack, field);
            elementSpec.put(sourceKey, targetPath);
        }
    }

    /**
     * 构建目标路径（支持 &n 索引引用）
     */
    private String buildTargetPath(Stack<String> pathStack, JsonMappingFieldDefine define) {
        StringBuilder sb = new StringBuilder();
        int stackSize = pathStack.size();
        String jsonPath = define.getJsonPath();
        for (int i = 0; i < stackSize; i++) {
            String key = pathStack.get(i);
            if (sb.length() > 0) {
                sb.append(".");
            }
            sb.append(key);
            if (jsonPath.contains("*")) {
                // 根据需求修改这里的索引层级，例如改为 1 或 3
                int indexLevel = 1;
                sb.append("[&").append(indexLevel).append("]");
            }
        }
        if (sb.length() > 0) {
            sb.append(".");
        }
        sb.append(define.getFieldCode());
        return sb.toString();
    }

    /**
     * 提取 JSON Path 最后的字段名（去除 [*]、["xxx"] 等符号）
     */
    private String extractLastFieldNameFromJsonPath(String jsonPath) {
        jsonPath = jsonPath.replace("[*]", "");
        if (jsonPath.startsWith("$.") && jsonPath.length() > 2) {
            String[] parts = jsonPath.substring(2).split("\\.");
            return parts[parts.length - 1];
        } else if (jsonPath.startsWith("$[")) {
            int endIdx = jsonPath.indexOf("]");
            if (endIdx > 0) {
                String raw = jsonPath.substring(2, endIdx);
                return raw.replaceAll("^['\"]|['\"]$", "");
            }
        }
        return jsonPath;
    }
}